/*!
 * gulp
 * $ npm install gulp gulp-ruby-sass gulp-cached gulp-uglify gulp-rename gulp-concat gulp-notify gulp-filter gulp-jshint gulp-rev-append gulp-cssnano gulp-imagemin browser-sync gulp-file-include gulp-autoprefixer del --save-dev
 */

// Load plugins
var gulp = require('gulp'), // 必须先引入gulp插件
    del = require('del'), // 文件删除
    sass = require('gulp-sass'), // sass 编译
    less = require('gulp-less'), // less 编译
    sourcemaps = require('gulp-sourcemaps'), //确保本地已安装gulp-sourcemaps [cnpm install gulp-sourcemaps --save-dev]
    cached = require('gulp-cached'), // 缓存当前任务中的文件，只让已修改的文件通过管道
    uglify = require('gulp-uglify'), // js 压缩
    rename = require('gulp-rename'), // 重命名
    concat = require('gulp-concat'), // 合并文件
    copy   = require('gulp-contrib-copy'),//不编译的文件直接copy
    notify = require('gulp-notify'), // 相当于 console.log()
    filter = require('gulp-filter'), // 过滤筛选指定文件
    jshint = require('gulp-jshint'), // js 语法校验
    rev = require('gulp-rev-append'), // 插入文件指纹（MD5）
    cssnano = require('gulp-cssnano'), // CSS 压缩
    imagemin = require('gulp-imagemin'), // 图片优化
    browserSync = require('browser-sync'), // 保存自动刷新
    connect = require('gulp-connect'), //热刷新(本地服务器)
    fileinclude = require('gulp-file-include'), // 可以 include html 文件
    autoprefixer = require('gulp-autoprefixer'), // 添加 CSS 浏览器前缀
    babel = require('gulp-babel'); // 添加 CSS 浏览器前缀
    plumber = require('gulp-plumber'), //gulp-plumber插件来忽略less编译错误
    GJSDuck = require('gulp-jsduck'),
    gjsduck = new GJSDuck(['--out', 'mydoc']);

//es6编译

// sass
gulp.task('sass', function () {
    return gulp.src('src/sass/**/*.scss', {
            style: 'expanded'
        }) // 传入 sass 目录及子目录下的所有 .scss 文件生成文件流通过管道并设置输出格式
        .pipe(cached('sass')) // 缓存传入文件，只让已修改的文件通过管道（第一次执行是全部通过，因为还没有记录缓存）
        .pipe(autoprefixer('last 6 version')) // 添加 CSS 浏览器前缀，兼容最新的5个版本
        .pipe(sass())
        .pipe(sourcemaps.init()) //资源地图创建
        .pipe(sourcemaps.write()) //资源地图写入
        .pipe(gulp.dest('dist/css')) // 输出到 dist/css 目录下（不影响此时管道里的文件流）
        .pipe(rename({
            suffix: '.min'
        })) // 对管道里的文件流添加 .min 的重命名
        .pipe(cssnano()) // 压缩 CSS
        .pipe(gulp.dest('dist/css')); // 输出到 dist/css 目录下，此时每个文件都有压缩（*.min.css）和未压缩(*.css)两个版本
});
// less
gulp.task('less', function () {
    return gulp.src('src/css/**/*.less', {
            style: 'expanded'
        }) // 传入 sass 目录及子目录下的所有 .scss 文件生成文件流通过管道并设置输出格式
        .pipe(plumber()) //忽略less编译错误
        .pipe(cached('less')) // 缓存传入文件，只让已修改的文件通过管道（第一次执行是全部通过，因为还没有记录缓存）
        .pipe(autoprefixer('last 6 version')) // 添加 CSS 浏览器前缀，兼容最新的5个版本
        .pipe(less({
            plugins: autoprefixer('last 6 version')
        }))
        .pipe(sourcemaps.init()) //资源地图创建
        .pipe(sourcemaps.write()) //资源地图写入
        .pipe(gulp.dest('src/css')) //输出未压缩的css文件
        .pipe(gulp.dest('dist/css')) //输出未压缩的css文件
        .pipe(rename({
            suffix: '.min'
        })) // 对管道里的文件流添加 .min 的重命名
        .pipe(cssnano()) // 压缩 CSS目录下，此时每个文件都有压缩（*.min.css）和未压缩(*.css)两个版本
        .pipe(gulp.dest('src/css')); // 输出到 dist/css 目录下（不影响此时管道里的文件流）
});
// css （拷贝 *.min.css，常规 CSS 则输出压缩与未压缩两个版本）
gulp.task('css', function () {
    return gulp.src('src/css/**/*.css')
        .pipe(cached('css'))
        .pipe(gulp.dest('dist/css')) // 把管道里的所有文件输出到 dist/css 目录
        .pipe(filter(['**/*', '!**/*.min.css'])) // 筛选出管道中的非 *.min.css 文件
        .pipe(autoprefixer({
            grid: true,
            browsers: ['last 6 versions']
        }))
        .pipe(connect.reload()) //页面热刷新
        .pipe(gulp.dest('dist/css')) // 把处理过的 css 输出到 dist/css 目录
        .pipe(rename({
            suffix: '.min'
        }))
        .pipe(cssnano())
        .pipe(gulp.dest('dist/css'));
});

// styleReload （结合 watch 任务，无刷新CSS注入）
gulp.task('styleReload', ['less', 'css'], function () {
    return gulp.src(['dist/css/**/*.css'])
        .pipe(cached('style'))
        .pipe(browserSync.reload({
            stream: true
        })); // 使用无刷新 browserSync 注入 CSS
});

// script （拷贝 *.min.js，常规 js 则输出压缩与未压缩两个版本）
gulp.task('script', function () {
    return gulp.src(['src/js/**/*.js'])
        .pipe(cached('script'))
        .pipe(gulp.dest('dist/js'))
        .pipe(filter(['**/*', '!**/*.min.js'])) // 筛选出管道中的非 *.min.js 文件
        // .pipe(jshint('.jshintrc')) // js的校验与合并，根据需要开启
        // .pipe(jshint.reporter('default'))
        // .pipe(concat('main.js'))
        .pipe(connect.reload()) //页面热刷新
        .pipe(babel({
            presets: ['es2015']
        })) //es6转码
        .pipe(gulp.dest('dist/js')) //输出js文件
        .pipe(rename({
            suffix: '.min'
        }))
        .pipe(uglify()) // 压缩js
        .pipe(gulp.dest('dist/js')); //输出压缩后的js文件
});

// image
gulp.task('image', function () {
    return gulp.src('src/images/**/*.{jpg,jpeg,png,gif,ico}')
        .pipe(cached('image'))//只让修改的文件通过管道
        .pipe(imagemin({
            optimizationLevel: 3, //类型：Number  默认：3  取值范围：0-7（优化等级）
            progressive: true, //类型：Boolean 默认：false 无损压缩jpg图片
            interlaced: true, //类型：Boolean 默认：false 隔行扫描gif进行渲染
            multipass: true, //类型：Boolean 默认：false 多次优化svg直到完全优化
        }))
        // 取值范围：0-7（优化等级）,是否无损压缩jpg图片，是否隔行扫描gif进行渲染，是否多次优化svg直到完全优化
        .pipe(connect.reload()) //页面热刷新
        .pipe(gulp.dest('dist/images'));
});

// html 编译 html 文件并复制字体
gulp.task('html', function () {
    return gulp.src('src/**/*.html')
        .pipe(fileinclude()) // include html
        .pipe(rev()) // 生成并插入 MD5
        .pipe(connect.reload()) //页面热刷新
        .pipe(gulp.dest('dist/'));
});

// clean 清空 dist 目录
gulp.task('clean', function () {
    return del('dist/**/*');
});

// build，关连执行全部编译任务
gulp.task('build', ['sass', 'less', 'css', 'script', 'image'], function () {
    gulp.start('html');
});
// copy 其他不编译的文件直接copy
gulp.task('copy',  function () {
    return gulp.src('dist/**/*.!(jpg|jpeg|png|gif|bmp|scss|less|js|html|tpl)')
        .pipe(copy())
        .pipe(gulp.dest('dist/'));
});
// default 默认任务，依赖清空dist目录和生成api文档
gulp.task('default', ['clean', 'doc'], function () {
    return gulp.start('build');
});
//doc生成javascript api文档
gulp.task('doc', function () {
    return gulp.src('./src/**/*.js')
        .pipe(gjsduck.doc());
});
// watch 开启本地服务器并监听
gulp.task('watch', ['less'], function () {
    browserSync.init({
        server: {
            proxy: "tbjyadmin.com", // 指定代理url
            notify: false, // 刷新不弹出提示
            baseDir: 'src' // 在 dist 目录下启动本地服务器环境，自动启动默认浏览器
        }
    });
    // 监控 html 文件，有变动则执行 html 任务
    gulp.watch('src/**/*.html', ['html']);
    // 监控 SASS 文件，有变动则执行CSS注入
    gulp.watch('src/sass/**/*.scss', ['styleReload']);
    // 监控 LESS 文件，有变动则执行CSS注入
    gulp.watch('src/less/**/*.less', ['styleReload']);
    // 监控 CSS 文件，有变动则执行CSS注入
    gulp.watch('src/css/**/*.css', ['styleReload']);
    // 监控 js 文件，有变动则执行 script doc任务
    gulp.watch('src/js/**/*.js', ['script', 'doc']);
    // 监控图片文件，有变动则执行 image 任务
    gulp.watch('src/images/**/*', ['image']);
    // 监听其他不编译的文件 有变化直接copy
    gulp.watch('src/**/*.!(jpg|jpeg|png|gif|bmp|scss|js|html)', ['copy']);
    // 监控 dist 目录下除 css 目录以外的变动（如js，图片等），则自动刷新页面
    gulp.watch(['src/**/*', 'src/css/**/*']).on('change', browserSync.reload);
});
